import type { Request, Response } from 'express';

import { z } from 'zod';

import { ProjectModel } from '../../../models/project';
import resp from '../../../utils/response';
import { createProjectDirectory, validateAppIds } from '../utils';

// api 参数校验
export const validator = z.object({
  // 项目下的应用ID数组
  apps: z.array(z.string().regex(/^[0-9a-fA-F]{24}$/, '应用ID格式不正确')).default([]),
  // 项目名称
  name: z
    .string()
    .min(1, '项目名称不能为空')
    .max(100, '项目名称不能超过100个字符')
    .transform(val => val?.trim()),
  // 项目描述（可选）
  remark: z
    .string()
    .max(500, '项目描述不能超过500个字符')
    .transform(val => val?.trim())
    .default(''),
});

/**
 * 创建应用
 * @param req
 * @param res
 * @description 此函数应与validateBody(validator)中间件一起使用
 * @example
 * POST /api/project
 * {
 *   "name": "示例应用",
 *   "apps": ["507f1f77bcf86cd799439011"],
 *   "remark": "这是一个应用项目"
 * }
 *
 * 成功响应:
 * {
 *   "success": true,
 *   "code": 200,
 *   "message": "应用创建成功",
 *   "data": {
 *     "_id": "507f1f77bcf86cd799439012",
 *     "name": "应用项目",
 *     "apps": ["507f1f77bcf86cd799439011"],
 *     "remark": "这是一个应用项目",
 *     "scripts": [],
 *     "createdAt": "2024-01-01T00:00:00.000Z",
 *     "updatedAt": "2024-01-01T00:00:00.000Z"
 *   }
 * }
 */
export const api = async (req: Request, res: Response): Promise<Response> => {
  try {
    const { apps, name, remark } = req.body as z.infer<typeof validator>;

    // 并行执行验证操作以提高性能
    const [existingProject, areAppsValid] = await Promise.all([
      ProjectModel.findOne({ name }),
      validateAppIds(apps),
    ]);

    // 检查应用名称是否已存在
    if (existingProject) {
      return resp.error(res, 400, '应用名称已存在');
    }

    // 检查代码仓库是否都存在
    if (!areAppsValid) {
      return resp.error(res, 400, '部分代码仓库不存在');
    }

    // 创建新项目
    const newProject = new ProjectModel({
      apps,
      name,
      remark,
      scripts: {
        desc: '',
        scripts: [], // 默认为空数组
        title: '',
      },
    });
    // 保存到数据库
    const savedProject = await newProject.save();
    // 异步创建项目文件夹（不影响响应）
    createProjectDirectory(savedProject._id.toString()).catch(error => {
      console.error(`项目 ${savedProject._id} 文件夹创建失败:`, error);
    });

    console.log(`项目创建成功: ${savedProject.name} (ID: ${savedProject._id})`);
    return resp.success(res, savedProject, '项目创建成功');
  } catch (e) {
    console.error('创建项目失败:', e);
    return resp.catch(res, e);
  }
};
